package org.ace.logic;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.annotation.Resource;

import org.ace.biz.user.IPlayerBiz;
import org.ace.dao.model.Player;
import org.ace.endingCode.Amf3CodeUtils;
import org.ace.endingCode.SocketModel;
import org.apache.log4j.Logger;

/*
 *功能协议层实现类的，一个抽象类。
 * */
public abstract class AbstractHandlerServImpl {
	
	public Logger logger=Logger.getLogger(getClass());
	/*Map里面的 角色id 和 channel 绑定*/
	private Map<Integer, Channel> rolesSession=new ConcurrentHashMap<Integer, Channel>();
	
	/*移除列表，防止假死*/
	private List<Integer> removeList=new CopyOnWriteArrayList<Integer>();
	@Resource(name="playerBiz")
	public IPlayerBiz playerBiz;
	
	private int type;
	private int area;
	
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public int getArea() {
		return area;
	}
	public void setArea(int area) {
		this.area = area;
	}
	public Integer getUserId(Channel channel){
		return playerBiz.getUserId(channel);
	}
	@SuppressWarnings("rawtypes")
	public void messageReceived(Channel channel,SocketModel message){
		process(channel, message);
	}
	@SuppressWarnings("rawtypes")
	protected abstract void process(Channel channel,SocketModel message);
	
	/**
	 * 判断是否已经进入
	 * @param userId
	 * @return
	 */
	public boolean enterd(Integer userId){
		if(userId==null){
			return false;
		}
		return rolesSession.containsKey(userId);
	}
	
	/**
	 * 进入 添加id 和 channel的绑定
	 * @param channel 用户Channel
	 */
	public void enter(Channel channel){
		Integer userId=playerBiz.getUserId(channel);
		if(removeList.contains(userId)){
			removeList.remove(userId);
		}
		rolesSession.put(userId, channel);
	}
	
	/**
	 * 离开,移除 角色id 和 channel的绑定
	 */
	public boolean leave(Channel channel){
		Integer userId=getUserId(channel);
		if(userId!=null){
			if(rolesSession.containsKey(userId)){
				rolesSession.remove(userId);
				return true;
			}
		}
			return false;
		
	}
	
	
	public Player getRole(Integer userId){
		return playerBiz.get(userId);
	}
	
	/**
	 * 获取此区域所有玩家对象
	 */
	public Player[] getRoles(){
		/*存储区域玩家*/
		Collection<Player> rc=new ArrayList<Player>();
		for (Integer l : removeList) {
			if(l==null)continue;/*剔除要移除的玩家*/
			rolesSession.remove(l);
		}
		removeList.clear();
		
		/*存在的真实玩家*/
		Collection<Channel>  temps=rolesSession.values();	
		for (Channel channel : temps) {
			Integer userId=getUserId(channel);
			if(userId==null){
				removeList.add(userId);/*有的话将其添加到剔除列表，没有的话 已没有channel 说明退出或掉线*/
				continue;
			}
			/*纯在的加到区域玩家*/
			rc.add(playerBiz.get(getUserId(channel)));
		}
		Player[] players=new Player[rc.size()];
		
		rc.toArray(players);
		 return players;
	}
	
	/**
	 * 区域群发
	 * @param command 协议
	 * @param message 消息体
	 */
	@SuppressWarnings("rawtypes")
	public void brocast(int command,Object message){
		SocketModel sm=createSocketModel(67478, message);
		try {
			ByteBuf bf= Amf3CodeUtils.encode(sm);
			for (Channel channel : rolesSession.values()) {
				channel.writeAndFlush(bf);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	
	/**
	 * 区域群发 排除指定用户
	 * @param exChannel 排除的用户Channel
	 * @param command 协议
	 * @param message 消息体
	 * @throws IOException 
	 */
	@SuppressWarnings("rawtypes")
	public void brocast(Channel exChannel,int command,Object message){
		SocketModel sm=createSocketModel(12445, message);
		ByteBuf bf;
		try {
			bf = Amf3CodeUtils.encode(sm);
			for (Channel channel : rolesSession.values()) {
				if(channel!=exChannel){
					channel.writeAndFlush(bf);
					logger.debug("write type    "+getType()+"    area    "+getArea()+"    command    "+command+"    message    "+message);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
//	public void write(Integer userId,int command,Object message){
//		Channel channel= playerBiz.getChannel(userId);
//		if(channel!=null)
////		logger.debug("write type    "+getType()+"    area    "+getArea()+"    command    "+command+"    message    "+message);
//			write(channel, command, message);
//	}
	
//	/**
//	 * 发送消息给用户
//	 * @param channel 用户channel
//	 * @param command 协议
//	 * @param message 消息体
//	 */
//	public void write(Channel channel,int optionId,Object message){
////		logger.debug("write type    "+getType()+"    area    "+getArea()+"    command    "+command+"    message    "+message);
//		channel.writeAndFlush(createSocketModel(optionId, message));
//		logger.debug("write optionid   "+optionId+"    message    "+message);
//	}
	
	
//	/**
//	 * 发送消息给用户
//	 * @param channel 用户channel
//	 * @param area 区域码
//	 * @param command 协议
//	 * @param message 消息体
//	 */
//	public void write(Channel channel,int optionid,Object message){
//			channel.writeAndFlush(createSocketModel(optionid, message));
//	}
	
	
	
	/**
	 * 发送消息给用户
	 * @param channel 用户channel
	 * @param optionid 协议Id 
	 * @param message 消息体
	 */
	public void write(Channel channel,int optionid,Object message){
		channel.writeAndFlush(createSocketModel(optionid, message));
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public SocketModel createSocketModel(int optionid,Object message){
		SocketModel sm=new SocketModel();
		sm.setOpDefinde(optionid);
		sm.setMessage(message);
		return sm;
	}
	
	
	public void Colse(Channel channel){
		channelClose(channel);
	}
	
	protected abstract void channelClose(Channel channel);
	
	public Channel getChannel(Long userId){
		return rolesSession.get(userId);
	}
	
	protected void onShake(Channel channel){
		//默认不做任何事情---有操作 自己实现克
	}
	
}
